using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;
using Facebook.Entity;
using Facebook.Controls;
using System.Threading;
using Notifications.Helper;
using APNotifications.Helper;

namespace APNotifications
{       

    public partial class frmMain : Form
    {
        #region Private Properies

        private Enums.Authentication _Authentication = Enums.Authentication.NotAuthenticated;       
        private int _UnreadMess, _Poke, _FriendReq, _GroupInv, _EventInv = 0;             
        private string _contentUrl, _downloadUrl, _ErrorMessage = string.Empty;
        private bool _ErrorShown, _showUpdate, _Shutdown = false;
        private bool _Startup = true;
        private frmSummary _frmSummary = new frmSummary();
        private Messaging _Messaging = new Messaging();

        
        #endregion

        #region Initialize Load Form

        public frmMain()
        {
            InitializeComponent();
            InitializeForm();
            this.taskbarNotify.SetBackgroundBitmap("skin.png", Color.FromArgb(255, 0, 255));
            this.taskbarNotify.SetCloseBitmap("close.bmp", Color.FromArgb(255, 0, 255), new Point(180, 8));
        }

        private void frmMain_Load(object sender, EventArgs e)
        {            

            ThreadInitialize();
         
            if (CheckForUpdate())
            {
                _showUpdate = true;                
            }                                               
        }

        private void InitializeForm()
        {
            this.timer1.Interval = Config.RefreshRate();
            InitializeTaskbarNotifier();
        }

        private void InitializeTaskbarNotifier()
        {
            this.taskbarNotify.ContentRectangle = new Rectangle(18, 35, 165, 60);            
        }        

        #endregion

        #region Initialize Authenticate Facebook

        protected void InitializefacebookService()
        {
            _Authentication = Enums.Authentication.Authenticating;
            this.facebookService.Dispose();
            this.facebookService = new Facebook.Components.FacebookService(Config.ProxyCredentials());
            this.facebookService.ApplicationKey = Config.api_key();
            this.facebookService.IsDesktopApplication = true;
            this.facebookService.Secret = Config.secret();
            this.facebookService.SessionKey = null;
            this.facebookService.UserId = null;
            _Authentication = Enums.Authentication.Authenticated;
        }

        #endregion

        #region Notifications

        private void ShowNotification(int TotalCount)
        {
            if (Config.ShowNotifications())
            {
             if(TotalCount > 0)
                {
                    try
                    {                        
                        _contentUrl = "http://www.facebook.com/home.php";
                        this.taskbarNotify.Show(string.Empty, "You have " + TotalCount.ToString() + " new facebook notifications", 200, 5000, 200);
                        if (Config.SoundOn())
                        {
                            Audio aud = new Audio();
                            aud.Play("notify.wav", aud.SND_FILENAME | aud.SND_ASYNC);
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowErrorBubble(ex);
                    }
                }
                else
                {
                    try
                    {                        
                        _contentUrl = "http://www.facebook.com/home.php";
                        this.taskbarNotify.Show(string.Empty, "You have no new facebook notifications", 200, 5000, 200);
                        if (Config.SoundOn())
                        {
                            Audio aud = new Audio();
                            aud.Play("notify.wav", aud.SND_FILENAME | aud.SND_ASYNC);
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowErrorBubble(ex);
                    }     
                }
            }            
        }

        private void ShowIndividualNotification(int Count, Enums.NotificationTypes NotificationType)
        {
            if (Config.ShowNotifications())
            {
                try
                {
                    string plural = string.Empty;

                    if (Count > 1)
                    {
                        plural = "s";
                    }
                    _contentUrl = "http://www.facebook.com/home.php";
                    this.taskbarNotify.Show(string.Empty, "You have " + Count.ToString() + " new " + NotificationType.ToString().Replace("_"," ") + plural, 200, 5000, 200);
                    if (Config.SoundOn())
                    {
                        Audio aud = new Audio();
                                                                      
                        aud.Play(Config.GetSoundToPlay("Sound" + NotificationType.ToString()), aud.SND_FILENAME | aud.SND_ASYNC);                       
                    }
                }
                catch (Exception ex)
                {
                    ShowErrorBubble(ex);
                }
            }
        }

        private void ShowUpdateNotification(string _downloadUrl)
        {            
            try
            {
                if (Config.SoundOn())
                {
                    Audio aud = new Audio();
                    aud.Play("notify.wav", aud.SND_FILENAME | aud.SND_ASYNC);
                }
                _contentUrl = _downloadUrl;
                this.taskbarNotify.Show(string.Empty, "New version of Notifications available. Click here to download", 250, 30000, 250);
            }
            catch (Exception ex)
            {
                ShowErrorBubble(ex);
                _ErrorShown = true;
            }
        }

        private void ShowErrorBubble(Exception _ex)
        {

            this.notifyIcon1.Icon = new Icon("facebookE.ico");
            if (!_ErrorShown)
            {
                this.notifyIcon1.ShowBalloonTip(5000, "Error", _ex.Message, ToolTipIcon.Error);
            }
            this.profile1.Visible = false;
            this.lnkMess.Visible = false;
            this.lnkGroup.Visible = false;
            this.lnkFriend.Visible = false;
            this.lnkEvent.Visible = false;
            this.lnkPoke.Visible = false;
            this.btnConnect.Visible = true;                                    
        }

        private void HandleConnectivityError(Exception ex)
        {
            if (ex.Message == "The remote server returned an error: (407) Proxy Authentication Required.")
            {
                this.txtAuthError.Text = ex.Message;
                this.lnkSettings.Visible = true;
            }
            else
            {
                this.txtAuthError.Text = ex.Message + " Will try reconnect shortly...";
            }

            this.txtAuthError.Visible = true;
            _Authentication = Enums.Authentication.NotAuthenticated;
            this.ShowErrorBubble(ex);
            _ErrorShown = true;
        }

        #endregion

        #region CheckForUpdate

        private bool CheckForUpdate()
        {
            Updater upd = new Updater(Config.UpdaterUrl(), Config.ApplicationName(), 
                Config.Version(), Config.UpdaterTimeout(),Config.ProxyCredentials());

            return upd.CheckForUpdate(ref _downloadUrl);            
        }

        #endregion

        #region TaskbarNotifierEvents

        private void CloseClick(object obj, EventArgs e)
        {
            //MessageBox.Show("Closed was Clicked");
        }

        private void TitleClick(object obj, EventArgs e)
        {
            //MessageBox.Show("Title was Clicked");
        }

        private void ContentClick(object obj, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(_contentUrl);
            }
            catch
            {
            }
        }
        #endregion

        #region Timer

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (_ErrorMessage != "The remote server returned an error: (407) Proxy Authentication Required." && _Authentication == Enums.Authentication.NotAuthenticated)
            {
                //Authenticate();
                ThreadInitialize();
            }
            else
            {                
                try
                {
                    ThreadBindNotifications();
                }
                catch (Exception ex)
                {
                    ShowErrorBubble(ex);
                }             
            }
        }

        #endregion

        #region Private Events

        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }

            if (e.Button != MouseButtons.Right)
            {
                this.Show();
                WindowState = FormWindowState.Normal;
                this.Activate();
            }
        }

        private void profileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }

            this.Show();
            WindowState = FormWindowState.Normal;
            this.Activate();
        }                    

        private void pbHeader_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }

            try
            {
                System.Diagnostics.Process.Start("http://www.facebook.com/home.php");
            }
            catch
            {
            }
        }        

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (_Authentication == Enums.Authentication.Authenticated)
            {
                _Startup = true;
                ThreadBindNotifications();
                //ShowNotification(_nCount);
            }
            else
            {
                Exception ex = new Exception("Not Authenticated");
                ShowErrorBubble(ex);
            }
        }        

        private void aboutFacebookNotifierToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }  
            Dynamic _Dynamic = new Dynamic(Enums.APControls.About);
            _Dynamic.downloadUrl = _downloadUrl;
            _Dynamic.Show();
        }

        private void notificationsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }  
            Dynamic _Dynamic = new Dynamic(Helper.Enums.APControls.Settings);
            _Dynamic.Show();            
        }     

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            timer1_Tick(sender, e);
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {           
            if ((!_Shutdown) && (e.CloseReason != CloseReason.WindowsShutDown))
            {
                e.Cancel = true;
                WindowState = FormWindowState.Minimized;
                Hide();
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            _Shutdown = true;
            Application.Exit();
        }

        private void lnkMess_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            frmFacebook Facebook = new frmFacebook("http://www.facebook.com/inbox");
            Facebook.Show();
        }

        private void lnkEvent_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            frmFacebook Facebook = new frmFacebook("http://www.facebook.com/reqs.php");
            Facebook.Show();
        }

        private void lnkGroup_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            frmFacebook Facebook = new frmFacebook("http://www.facebook.com/reqs.php");
            Facebook.Show();
        }

        private void lnkFriend_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            frmFacebook Facebook = new frmFacebook("http://www.facebook.com/reqs.php");
            Facebook.Show();
        }

        private void lnkPoke_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            frmFacebook Facebook = new frmFacebook("http://www.facebook.com/home.php");
            Facebook.Show();
        }

        private void composeMessageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            frmFacebook Facebook = new frmFacebook("http://www.facebook.com/inbox/?compose");
            Facebook.Show();
        }

        private void lnkSettings_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            Dynamic _Dynamic = new Dynamic(Helper.Enums.APControls.Settings);
            _Dynamic.Show();
        }

        private void showSummaryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }
            _frmSummary.Show();
            _frmSummary.Activate();
        }

        private void toolStripMenuItemIM_Click(object sender, EventArgs e)
        {
            if (_Messaging.IsDisposed)
            {
                _Messaging = new Messaging();
                _Messaging.Show();
            }
            else
            {
                _Messaging.Show();
                _Messaging.Activate();
            }
        }

        private void lnkStatus_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            
            if (Config.SoundOn())
            {
                Audio aud = new Audio();
                aud.Play("action.wav", aud.SND_FILENAME | aud.SND_ASYNC);
            }            

            if (lnkStatus.Text == "              Save")
            {
                facebookService.SetStatus(txtSatus.Text);
                profile1.Status = txtSatus.Text;
                txtSatus.Visible = false;
                lnkStatus.Text = "Update Status";
            }
            else
            {
                lnkStatus.Text = "              Save";
                txtSatus.Text = profile1.Status;
                txtSatus.Visible = true;
            }
        }

        #endregion

        #region Threading

        private void ThreadBindNotifications()
        {
            this.backgroundWorker1.RunWorkerAsync();
        }

        private void ThreadInitialize()
        {
            this.backgroundWorker2.RunWorkerAsync();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            int UnreadMess,Poke,FriendReq,GroupInv,EventInv,TotalCount = 0;

            if (_Authentication == Enums.Authentication.Authenticated)
            {
                try
                {                    

                    Facebook.Entity.Notifications _n = new Facebook.Entity.Notifications();
                    _n = this.facebookService.GetNotifications();                    
                    UnreadMess = _n.UnreadMessageCount;
                    Poke = _n.UnreadPokeCount;
                    FriendReq = _n.FriendRequests.Count;
                    GroupInv = _n.GroupInvites.Count;
                    EventInv = _n.EventInvites.Count;

                    this.lblUnreadEventInviteCount.Text = EventInv.ToString();
                    this.lblUnreadFriendRequestCount.Text = FriendReq.ToString();
                    this.lblUnreadGroupInviteCount.Text = GroupInv.ToString();
                    this.lblUnreadMessageCount.Text = UnreadMess.ToString();
                    this.lblUnreadPokeCount.Text = Poke.ToString();

                    this._frmSummary.bindNotifications(UnreadMess, Poke, FriendReq, EventInv + GroupInv);                    

                    if (this.lblUnreadEventInviteCount.Text != "0") { this.lnkEvent.Visible = true; } else { this.lnkEvent.Visible = false; }
                    if (this.lblUnreadFriendRequestCount.Text != "0") { this.lnkFriend.Visible = true; } else { this.lnkFriend.Visible = false; }
                    if (this.lblUnreadGroupInviteCount.Text != "0") { this.lnkGroup.Visible = true; } else { this.lnkGroup.Visible = false; }
                    if (this.lblUnreadMessageCount.Text != "0") { this.lnkMess.Visible = true; } else { this.lnkMess.Visible = false; }
                    if (this.lblUnreadPokeCount.Text != "0") { this.lnkPoke.Visible = true; } else { this.lnkPoke.Visible = false; }

                    TotalCount = UnreadMess + Poke + FriendReq + GroupInv + EventInv;

                    if (TotalCount > 0)
                    {
                        this.notifyIcon1.Icon = new Icon("FacebookM.ico");
                    }
                    else
                    {
                        this.notifyIcon1.Icon = new Icon("Facebook.ico");
                    }

                    //Checks if Startup

                    if (_Startup == true)
                    {
                        this.ShowNotification(TotalCount);
                        _Startup = false;

                        if (_showUpdate)
                        {
                            this.ShowUpdateNotification(_downloadUrl);
                            _showUpdate = false;
                        }
                    }
                    else
                    {
                        if (UnreadMess > _UnreadMess)
                        {
                            this.ShowIndividualNotification(UnreadMess - _UnreadMess, Enums.NotificationTypes.unread_message);
                        }
                        if (Poke > _Poke)
                        {
                            this.ShowIndividualNotification(Poke - _Poke, Enums.NotificationTypes.unread_poke);
                        }
                        if (FriendReq > _FriendReq)
                        {
                            this.ShowIndividualNotification(FriendReq - _FriendReq, Enums.NotificationTypes.friend_invite);
                        }
                        if (GroupInv > _GroupInv)
                        {
                            this.ShowIndividualNotification(GroupInv - _GroupInv, Enums.NotificationTypes.group_invite);
                        }
                        if (EventInv > _EventInv)
                        {
                            this.ShowIndividualNotification(EventInv - _EventInv, Enums.NotificationTypes.event_invite);
                        }
                    }

                    _UnreadMess = UnreadMess;
                    _Poke = Poke;
                    _FriendReq = FriendReq;
                    _GroupInv = GroupInv;
                    _EventInv = EventInv;                    
                    
                    this.MainMenuItem.Text = "Notifications (" + TotalCount.ToString() + ")";
                    this.notifyIcon1.Text = "Notifications (" + TotalCount.ToString() + ")";
                }
                catch (Exception ex)
                {
                    this.HandleConnectivityError(ex);
                }
            }
        }

        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            User _me = null;

            try
            {

                if (_Authentication == Enums.Authentication.NotAuthenticated)
                {
                    _Authentication = Enums.Authentication.Authenticating;
                    this.facebookService.Dispose();
                    this.facebookService = new Facebook.Components.FacebookService(Config.ProxyCredentials());
                    this.facebookService.ApplicationKey = Config.api_key();
                    this.facebookService.IsDesktopApplication = true;
                    this.facebookService.Secret = Config.secret();
                    this.facebookService.SessionKey = null;
                    this.facebookService.UserId = null;
                    
                    this.txtAuthError.Text = "Connecting...";

                    _me = this.facebookService.GetUserInfo();
                    _Authentication = Enums.Authentication.Authenticated;

                    this.profile1.User = _me;
                    this.profile1.Visible = true;
                    this.btnConnect.Visible = false;
                    this.txtAuthError.Visible = false;
                    this.lnkSettings.Visible = false;
                    this.notifyIcon1.Icon = new Icon("Facebook.ico");
                    _ErrorShown = false;
                }
                if (_Authentication == Enums.Authentication.Authenticated)
                {
                    ThreadBindNotifications();
                    this._frmSummary.Show();
                }                
            }
            catch (Exception ex)
            {
                this.HandleConnectivityError(ex);
            }
        }

        #endregion 



    }    

}